package abc.filter;

import abc.base.AbcBaseController;
import abc.base.BaseController;
import abc.config.DatasourceConfigure;
import abc.utils.RequestUtil;
import abc.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.util.List;

@Slf4j
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestMatchSchemaFilter implements WebFilter {

    private volatile ThreadLocal<String> localDbName = new ThreadLocal<>();

    private volatile ThreadLocal<String> localTable = new ThreadLocal<>();

    private volatile ThreadLocal<Class> localControllerClass = new ThreadLocal<>();

    @Autowired
    DatasourceConfigure datasourceConfigure;

    private ServerWebExchange exchange;

    public ServerWebExchange getExchange() {
        return exchange;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        this.exchange = exchange;
        setDBName(exchange);
        return chain.filter(exchange);
    }

    private void setDBName(ServerWebExchange exchange) {
        localTable.remove();
        localControllerClass.remove();
        List<String> params = StringUtil.splitString2List(exchange.getRequest().getPath().value(), "/");
        if(params.size()<3) {
            return;
        }
        datasourceConfigure.getDatasource().entrySet().forEach(a-> {
            if(params.get(2).equals(a.getKey())) {
                if(StringUtil.isNotEmpty(a.getValue().getName())) {
                    localDbName.set(a.getValue().getName());
                    log.info("set dbname " + localDbName.get());
                }
            }
        });
    }

    public String getDBName() {
        return localDbName.get();
    }

    public String getTableName() {
        return getTableName(localControllerClass.get());
    }
    public <T extends AbcBaseController> String getTableName(Class<?> conntroller) {
        if(StringUtil.isEmpty(localTable.get())) {
            if(conntroller == null) {
                return null;
            }
            localTable.set(RequestUtil.getTableName(conntroller.getAnnotation(RequestMapping.class)));
            log.info("set table name " + localTable.get());
        }
        if(localControllerClass.get() == null) {
            localControllerClass.set(conntroller);
        }
        return localTable.get();
    }

    public <T> Class<T> getConntrollerClass() {
        return localControllerClass.get();
    }
}
